package org.lds.hotkey.console.business.currhotkey.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.lds.hotkey.common.model.dto.ResultDTO;
import org.lds.hotkey.common.model.pojo.OrderBy;
import org.lds.hotkey.common.model.pojo.PageResult;
import org.lds.hotkey.console.business.app.service.AppService;
import org.lds.hotkey.console.business.currhotkey.converter.*;
import org.lds.hotkey.console.business.currhotkey.entity.CurrHotKey;
import org.lds.hotkey.console.business.currhotkey.mapper.CurrHotKeyMapper;
import org.lds.hotkey.console.business.currhotkey.model.request.*;
import org.lds.hotkey.console.business.currhotkey.model.response.*;
import org.lds.hotkey.console.business.currhotkey.service.CurrHotKeyBaseService;
import org.lds.hotkey.console.remote.model.request.CurrHotKeySaveRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 *  基础服务实现类
 *
 * @author lidongsheng
 * @since 2024-07-15
 */
@Slf4j
@Service
public class CurrHotKeyBaseServiceImpl implements CurrHotKeyBaseService {

    @Autowired
    private AppService appService;

    @Autowired
    private  CurrHotKeyMapper currHotKeyMapper;

    @Autowired
    private CurrHotKeyBaseCreateRequestToEntityConverter currHotKeyBaseCreateRequestToEntityConverter;

    @Autowired
    private CurrHotKeyBaseUpdateRequestToEntityConverter currHotKeyBaseUpdateRequestToEntityConverter;

    @Autowired
    private CurrHotKeyBaseListRequestToEntityConverter currHotKeyBaseListRequestToEntityConverter;

    @Autowired
    private CurrHotKeyToBaseResponseConverter currHotKeyToBaseResponseConverter;

    @Autowired
    private CurrHotKeyBaseListPageRequestToEntityConverter currHotKeyBaseListPageRequestToEntityConverter;

    @Autowired
    private CurrHotKeyBaseGetByKeyRequestToEntityConverter currHotKeyBaseGetByKeyRequestToEntityConverter;

    @Autowired
    private CurrHotKeyBaseDeleteRequestToEntityConverter currHotKeyBaseDeleteRequestToEntityConverter;

    @Override
    @Transactional
    public ResultDTO<CurrHotKeyBaseResponse> createCurrHotKey(CurrHotKeyBaseCreateRequest request) {
        if(needCheckApp(request.getAppId())) {
            appService.existApp(request.getAppId());
        }

        try {
            CurrHotKey  currHotKey = currHotKeyBaseCreateRequestToEntityConverter.convert(request);
            currHotKeyMapper.insert( currHotKey);
            CurrHotKeyBaseResponse response = currHotKeyToBaseResponseConverter.convert( currHotKey);
            return ResultDTO.success(response);
        }

        catch (DuplicateKeyException e) {
            return ResultDTO.fail("DATA_REPEAT", "数据重复");
        }
    }

    @Override
    @Transactional
    public ResultDTO<Boolean> saveCurrHotKey(CurrHotKeySaveRequest request) {
        CurrHotKey currHotKeyByKey = getCurrHotKeyByKey(CurrHotKeyBaseGetByKeyRequest.builder().appId(request.getAppId()).key(request.getKey()).build());
        if (Objects.isNull(currHotKeyByKey)) {
            // 创建
            createCurrHotKey(CurrHotKeyBaseCreateRequest.builder().appId(request.getAppId()).key(request.getKey()).duration(request.getDuration()).build());
        } else {
            // 更新
            updateCurrHotKey(CurrHotKeyBaseUpdateRequest.builder().id(currHotKeyByKey.getId()).duration(request.getDuration()).build());
        }
        return ResultDTO.success(true);
    }

    @Transactional
    @Override
    public ResultDTO<CurrHotKeyBaseBatchCreateResponse> batchCreateCurrHotKey(CurrHotKeyBaseBatchCreateRequest request) {
        CurrHotKeyBaseBatchCreateResponse response = CurrHotKeyBaseBatchCreateResponse.builder()
            .responses(request.getRequests().stream().map(this::createCurrHotKey).collect(Collectors.toList()))
            .build();
        return ResultDTO.success(response);
    }

    @Transactional
    @Override
    public ResultDTO<CurrHotKeyBaseDeleteResponse> deleteCurrHotKey(CurrHotKeyBaseDeleteRequest request) {
        currHotKeyMapper.deleteById(request.getId());

        CurrHotKeyBaseDeleteResponse response = CurrHotKeyBaseDeleteResponse.builder().request(request).build();
        return ResultDTO.success(response);
    }

    @Transactional
    @Override
    public ResultDTO<CurrHotKeyBaseBatchDeleteResponse> batchDeleteCurrHotKey(CurrHotKeyBaseBatchDeleteRequest request) {
        CurrHotKeyBaseBatchDeleteResponse response = CurrHotKeyBaseBatchDeleteResponse.builder()
                .responses(request.getRequests().stream().map(this::deleteCurrHotKey).collect(Collectors.toList()))
                .build();
        return ResultDTO.success(response);
    }

    @Transactional
    @Override
    public ResultDTO<CurrHotKeyBaseResponse> updateCurrHotKey(CurrHotKeyBaseUpdateRequest request) {
        try {
            CurrHotKey currHotKey = currHotKeyBaseUpdateRequestToEntityConverter.convert(request);
            currHotKeyMapper.updateById(currHotKey);
            CurrHotKeyBaseResponse response = currHotKeyToBaseResponseConverter.convert(currHotKey);
            return ResultDTO.success(response);
        }

        catch (DuplicateKeyException e) {
            return ResultDTO.fail("DATA_REPEAT", "数据重复");
        }
    }

    @Transactional
    @Override
    public ResultDTO<CurrHotKeyBaseBatchUpdateResponse> batchUpdateCurrHotKey(CurrHotKeyBaseBatchUpdateRequest request) {
        CurrHotKeyBaseBatchUpdateResponse response = CurrHotKeyBaseBatchUpdateResponse.builder()
                .requests(request.getRequests().stream().map(this::updateCurrHotKey).collect(Collectors.toList()))
                .build();
        return ResultDTO.success(response);
    }

    private boolean needCheckApp(Long appId) {
        return appId != null && appId != 0L;
    }

    @Override
    public ResultDTO<CurrHotKeyBaseResponse> getCurrHotKeyById(CurrHotKeyBaseGetByIdRequest request) {
        CurrHotKey currHotKey =  currHotKeyMapper.selectById(request.getId());
        if (currHotKey == null) return ResultDTO.success();

        CurrHotKeyBaseResponse response = currHotKeyToBaseResponseConverter.convert(currHotKey);
        return ResultDTO.success(response);
    }

    @Override
    public ResultDTO<CurrHotKeyBaseListResponse> getCurrHotKeyByIds(CurrHotKeyBaseGetByIdsRequest request) {
        List<CurrHotKey> list = request.getIds().stream().map(id -> currHotKeyMapper.selectById(id)).collect(Collectors.toList());
        return ResultDTO.success(CurrHotKeyBaseListResponse.builder()
                .currHotKeys(list.stream().map(currHotKey -> currHotKeyToBaseResponseConverter.convert(currHotKey)).collect(Collectors.toList()))
                .build());
    }

    @Override
    public CurrHotKey getCurrHotKeyByKey(CurrHotKeyBaseGetByKeyRequest request) {
        if (request == null) return null;
        return  currHotKeyMapper.selectOne(new QueryWrapper<>(currHotKeyBaseGetByKeyRequestToEntityConverter.convert(request)));
    }

    @Override
    public ResultDTO<CurrHotKeyBaseListResponse> listCurrHotKey(CurrHotKeyBaseListRequest request) {
        QueryWrapper<CurrHotKey> wrapper = new QueryWrapper<>(currHotKeyBaseListRequestToEntityConverter.convert(request));
        if (StringUtils.isNotEmpty(request.getOrderByKey())) {
            wrapper.orderByDesc(request.getOrderByKey());
        }

        List<CurrHotKey> currHotKeys =  currHotKeyMapper.selectList(wrapper);

        CurrHotKeyBaseListResponse response = CurrHotKeyBaseListResponse.builder()
                    .currHotKeys(currHotKeys.stream().map(currHotKeyToBaseResponseConverter::convert).collect(Collectors.toList()))
                    .build();
        return ResultDTO.success(response);
    }

    @Override
    public ResultDTO<CurrHotKeyBaseListResponse> listAllCurrHotKey(OrderBy orderBy) {
        CurrHotKeyBaseListRequest currHotKeyRequest = CurrHotKeyBaseListRequest.builder().build();
        currHotKeyRequest.setOrderByKey(orderBy.getOrderByKey());
        return listCurrHotKey(currHotKeyRequest);
    }

    @Override
    public ResultDTO<PageResult<CurrHotKeyBaseResponse>> listCurrHotKeyPage(CurrHotKeyBaseListPageRequest request) {
        Page<CurrHotKey> page = new Page<>(request.getPageNum(), request.getPageSize(), true);

        QueryWrapper<CurrHotKey> wrapper = new QueryWrapper<>(currHotKeyBaseListPageRequestToEntityConverter.convert(request));
        if (StringUtils.isNotEmpty(request.getOrderByKey())) {
            if (request.getOrderByDesc() != null && request.getOrderByDesc().booleanValue() == false) {
                wrapper.orderByAsc(request.getOrderByKey());
            } else {
                wrapper.orderByDesc(request.getOrderByKey());
            }
        }

        IPage<CurrHotKey> pageResult =  currHotKeyMapper.selectPage(page, wrapper);

        PageResult<CurrHotKeyBaseResponse> response = new PageResult(
        pageResult.getTotal(), pageResult.getPages(), pageResult.getCurrent(), pageResult.getSize(),
        pageResult.getRecords().stream().map(currHotKeyToBaseResponseConverter::convert).collect(Collectors.toList()));
        return ResultDTO.success(response);
    }

    @Override
    public ResultDTO<CurrHotKeyBaseBatchCreateResponse> batchCreateCurrHotKeyAsync(CurrHotKeyBaseBatchCreateRequest request) {
        CurrHotKeyBaseBatchCreateResponse response = CurrHotKeyBaseBatchCreateResponse.builder()
                .responses(request.getRequests().parallelStream().map(this::createCurrHotKey).collect(Collectors.toList()))
                .build();
        return ResultDTO.success(response);
    }

    @Override
    public ResultDTO<CurrHotKeyBaseBatchDeleteResponse> batchDeleteCurrHotKeyAsync(CurrHotKeyBaseBatchDeleteRequest request) {
        CurrHotKeyBaseBatchDeleteResponse response = CurrHotKeyBaseBatchDeleteResponse.builder()
                .responses(request.getRequests().parallelStream().map(this::deleteCurrHotKey).collect(Collectors.toList()))
                .build();
        return ResultDTO.success(response);
    }

    @Override
    public ResultDTO<CurrHotKeyBaseBatchUpdateResponse> batchUpdateCurrHotKeyAsync(CurrHotKeyBaseBatchUpdateRequest request) {
        CurrHotKeyBaseBatchUpdateResponse response = CurrHotKeyBaseBatchUpdateResponse.builder()
                .requests(request.getRequests().parallelStream().map(this::updateCurrHotKey).collect(Collectors.toList()))
                .build();
        return ResultDTO.success(response);
    }

}
